package controleur;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import modele.Equipe;
import modele.Match;
import modele.Pronostique;
import modele.Utilisateur;
import vue.FenetrePrincipale;

public class Controleur {

	private ArrayList<Utilisateur> alUtilisateurs;
	private ArrayList<Match> alMatchs;
	private Utilisateur utilisateurCourant;
	private ArrayList<Equipe> alEquipes;

	public Controleur() {

		alUtilisateurs = new ArrayList<Utilisateur>();
		alMatchs = new ArrayList<Match>();
		alEquipes = new ArrayList<Equipe>();

		// On charge la liste des utilisateurs
		chargerListeUtilisateurs();
		// On charge les matchs à pronostiquer
		chargerListeMatchsApronostiquer();
		// On charge la liste des équipes
		chargerListeEquipes();
		
		Utilisateur userCourant = new Utilisateur("gui", "gui", 0);
		Utilisateur val = new Utilisateur("val", "val", 0);
		/** @todo JUSTE POUR LES TESTS */
		if (alUtilisateurs.size() <= 1) {
			alUtilisateurs.add(val);
			alUtilisateurs.add(userCourant);
			alUtilisateurs.add(new Utilisateur("rom", "rom", 0));
		}

		/** @todo JUSTE POUR LES TESTS */
		if (alEquipes.size() <= 1) {
			Equipe eq1 = new Equipe("Le Havre", null);
			Equipe eq2 = new Equipe("Marseille", null);
			Equipe eq3 = new Equipe("Montréal", null);
			Equipe eq4 = new Equipe("Paris", null);
			Equipe eq5 = new Equipe("Lyon", null);
			Equipe eq6 = new Equipe("Saint Etienne", null);
			Equipe eq7 = new Equipe("Valencienne", null);
			Equipe eq8 = new Equipe("Sochaux", null);
			Equipe eq9 = new Equipe("Monaco", null);
			Equipe eq10 = new Equipe("Montpellier", null);
			Equipe eq11 = new Equipe("Lille", null);
			Equipe eq12 = new Equipe("Rennes", null);
			Equipe eq13 = new Equipe("Nantes", null);
			Equipe eq14 = new Equipe("Bordeaux", null);
			Equipe eq15 = new Equipe("Nice", null);
			Equipe eq16 = new Equipe("Lens", null);
			Equipe eq17 = new Equipe("Toulouse", null);
			Equipe eq18 = new Equipe("Guingamp", null);
			Equipe eq19 = new Equipe("Ajaccio", null);
			Equipe eq20 = new Equipe("Reims", null);

			alEquipes.add(eq1);
			alEquipes.add(eq2);
			alEquipes.add(eq3);
			alEquipes.add(eq4);
			alEquipes.add(eq5);
			alEquipes.add(eq6);
			alEquipes.add(eq7);
			alEquipes.add(eq8);
			alEquipes.add(eq9);
			alEquipes.add(eq10);
			alEquipes.add(eq11);
			alEquipes.add(eq12);
			alEquipes.add(eq13);
			alEquipes.add(eq14);
			alEquipes.add(eq15);
			alEquipes.add(eq16);
			alEquipes.add(eq17);
			alEquipes.add(eq18);
			alEquipes.add(eq19);
			alEquipes.add(eq20);

			SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
			Date dateMatch = null, dateMatch2 = null, dateMatch1 = null;
			try {
				dateMatch1 = f.parse("2012-11-11");
				dateMatch = f.parse("2013-04-07");
				dateMatch2 = f.parse("2013-11-30");
			} catch (ParseException e) {
				e.printStackTrace();
			}

			Match match1 = new Match(eq2, eq1, dateMatch1, "", -1, -1);
			Match match2 = new Match(eq3, eq2, dateMatch2, "", -1, -1);
			Match match3 = new Match(eq3, eq4, dateMatch, "", -1, -1);
			Match match4 = new Match(eq5, eq6, dateMatch, "", -1, -1);
			Match match5 = new Match(eq7, eq8, dateMatch, "", -1, -1);
			alMatchs.add(match1);
			alMatchs.add(match2);
			alMatchs.add(match3);
			alMatchs.add(match4);
			alMatchs.add(match5);
			Pronostique prono = new Pronostique(match1,1,0,-1);
			Pronostique prono1 = new Pronostique(match2,1,2,-1);
			Pronostique prono2 = new Pronostique(match3,2,0,-1);
			Pronostique prono3 = new Pronostique(match4,2,0,-1);
			Pronostique prono4 = new Pronostique(match5,2,0,-1);
			
			ArrayList<Pronostique> alProno = new ArrayList<Pronostique>();
			alProno.add(prono);
			alProno.add(prono1);
			alProno.add(prono2);
			alProno.add(prono3);
			alProno.add(prono4);
			userCourant.setListePronostique(alProno);
			
			alProno = new ArrayList<Pronostique>();
			Pronostique prono3a = new Pronostique(match1,1,2,-1);
			alProno.add(prono3a);
			val.setListePronostique(alProno);
			
			eq1.addMatch(match1);
			eq2.addMatch(match1);
			eq2.addMatch(match2);
			eq3.addMatch(match2);
			eq3.addMatch(match3);
			eq4.addMatch(match3);
			eq5.addMatch(match4);
			eq6.addMatch(match4);
			eq7.addMatch(match5);
			eq8.addMatch(match5);
//
//			alMatchs.add(match1);
//			alMatchs.add(match2);
//			alMatchs.add(match3);
			

			sauvegarderListeEquipes();
			sauvegarderListeMatchsApronostiquer();
		}
		this.utilisateurCourant = null;

		// Si le compte admin n'existe pas encore, on le crée
		if (!pseudoExiste("admin")) {
			ajouterUtilisateur(new Utilisateur("admin", "admin", 0, true));
		}
	}

	public Utilisateur getUtilisateurCourant() {
		return utilisateurCourant;
	}

	public void setUtilisateurCourant(Utilisateur userCourant) {
		this.utilisateurCourant = userCourant;
	}

	/**
	 * Permet de vérifier si un pseudo existe ou pas, utilisé lors de
	 * l'inscription
	 * 
	 * @param newUser
	 * @return
	 */
	public boolean pseudoExiste(String newUser) {

		boolean pseudoExiste = false;
		for (Utilisateur user : alUtilisateurs) {
			if (user.getPseudo().equals(newUser))
				pseudoExiste = true;
		}

		return pseudoExiste;
	}

	/**
	 * Utilisé lors de la connexion, verifie si tout est correct
	 * 
	 * @param user
	 * @return
	 */
	public boolean utilisateurExiste(Utilisateur utilisateur) {
		boolean pseudoExiste = false;
		for (Utilisateur user : alUtilisateurs) {
			if (user.getPseudo().equals(utilisateur.getPseudo())
					&& user.getMdp().equals(utilisateur.getMdp())) {
				pseudoExiste = true;
				this.utilisateurCourant = user;
			}
		}

		return pseudoExiste;
	}

	public void ajouterUtilisateur(Utilisateur newUser) {
		alUtilisateurs.add(newUser);
		sauvegarderListeUtilisateurs();
	}

	public void supprimerUtilisateur(Utilisateur utilisateur) {
		Utilisateur userASuppr = null;
		for (Utilisateur user : alUtilisateurs) {
			// On ne peut pas supprimer l'admin
			if (!utilisateur.getPseudo().equals("admin")
					&& user.getPseudo().equals(utilisateur.getPseudo()))
				userASuppr = user;
		}
		if (userASuppr != null)
			alUtilisateurs.remove(userASuppr);

		/** @todo modifier la liste des pseudos sur l'accueil */
		sauvegarderListeUtilisateurs();
	}
	
	public boolean ajouterEquipe(String nomEquipe) {
		Equipe equipe = getEquipeViaNom(nomEquipe);
		if(equipe == null) {
			Equipe newEq = new Equipe(nomEquipe, null);
			alEquipes.add(newEq);
			sauvegarderListeEquipes();
		}
		return (equipe == null);
	}
	
	public ArrayList<Utilisateur> getUtilisateurs() {
		return alUtilisateurs;
	}

	public ArrayList<Match> getMatchsAPronostiquer() {
		return alMatchs;
	}

	public ArrayList<Equipe> getEquipes() {
		return alEquipes;
	}

	public void removeList()
	{
		alMatchs.removeAll(alMatchs);	
		sauvegarderListeMatchsApronostiquer();

	}
	public void addMatchsAPronostiquer(Match m) {
		alMatchs.add(m);
		sauvegarderListeMatchsApronostiquer();
	}

	public void calculPtsProno(Match match) {
		int scoreEq1 = match.getScoreEquipe1();
		int scoreEq2 = match.getScoreEquipe2();
		// Si -1, eq2 a gagné, si 1, eq1 a gagné, si 0, match nul
		int resultatMatch = (scoreEq1 - scoreEq2 < 0) ? -1 : (scoreEq1 - scoreEq2 > 0) ? 1 : 0;
		int pronoEq1, pronoEq2, pronoMatch, nbPtsGagnes;
		for (Utilisateur util : alUtilisateurs) {
			for (Pronostique prono : util.getListePronostique()) {
				Match matchProno = prono.getMatch();
				if (match.isSameMatch(matchProno)) {
					pronoEq1 = prono.getScoreEquipe1();
					pronoEq2 = prono.getScoreEquipe2();
					// Si -1, eq2 a gagné, si 1, eq1 a gagné, si 0, match nul
					pronoMatch = (pronoEq1 - pronoEq2 < 0) ? -1 : (pronoEq1 - pronoEq2 > 0) ? 1 : 0;
					
					nbPtsGagnes = 0;
					//Score exact => 3pts
					if (pronoEq1 == scoreEq1 && pronoEq2 == scoreEq2)
						nbPtsGagnes = 3;
					// Résultat exact mais mauvais score => 1pt
					else if (pronoMatch == resultatMatch)
						nbPtsGagnes = 1;
					
					//S'il a modifié un prono déjà validé et que le nouveau gain est différent du précédent
					if(prono.getPtObtenus() > 0 && nbPtsGagnes != prono.getPtObtenus()) {
						int ptGGAvant = prono.getPtObtenus();
						util.setNbPts(util.getNbPts() - ptGGAvant + nbPtsGagnes);
					} else if (nbPtsGagnes > 0)
						util.setNbPts(util.getNbPts() + nbPtsGagnes);
					prono.setPtObtenus(nbPtsGagnes);
					
					
					System.out.println("Point gagné: "+ prono.getMatch().getEquipe1()+ " "+prono.getMatch().getEquipe2()+" "+prono.getPtObtenus());
				}
			}
		}
	}

	/**
	 * Retourne une équipe à partir de son nom
	 * 
	 * @param nomEquipe
	 * @return
	 */
	public Equipe getEquipeViaNom(String nomEquipe) {
		Equipe equipe = null;
		for (Equipe eq : alEquipes) {
			if (eq.getNom().equals(nomEquipe)) {
				equipe = eq;
				break;
			}
		}
		return equipe;
	}

	/**
	 * Retourne un match à partir d'une date et du nom d'une équipe dans l'al de
	 * match déjà programmée
	 * 
	 * @param dateMatch
	 * @param equipe
	 * @return
	 */
	public Match getMatchViaInfo(Date dateMatch, String nomEquipe) {
		return getMatchViaInfo(dateMatch, nomEquipe, alMatchs);
	}

	/**
	 * Retourne un match à partir d'une date et du nom d'une équipe dans une al
	 * donnée en paramètre
	 * 
	 * @param dateMatch
	 * @param equipe
	 * @param alMatchTmp
	 * @return
	 */
	public Match getMatchViaInfo(Date dateMatch, String nomEquipe, ArrayList<Match> alMatchTmp) {
		Equipe equipe = getEquipeViaNom(nomEquipe);
		Match matchRech = null;
		for (Match match : alMatchTmp) {
			if (match.getDate().equals(dateMatch)
					&& (match.getEquipe1().getNom().equals(equipe.getNom()) || match.getEquipe2().getNom().equals(equipe.getNom()))) {
				matchRech = match;
				break;
			}
		}
		return matchRech;
	}

	/**
	 * Verifie si un match existe déjà pour une date et 2 équipes données dans
	 * l'arraylist de match déjà programmé
	 * 
	 * @param dateMatch
	 * @param eq1
	 * @param eq2
	 * @return
	 */
	public boolean isMatchExist(Match match) {
		return isMatchExist(match, alMatchs);
	}

	/**
	 * Verifie si un match existe déjà pour une date et 2 équipes données dans
	 * l'arraylist de match en parametre
	 * 
	 * @param match
	 * @param alMatchTmp
	 * @return
	 */
	public boolean isMatchExist(Match match, ArrayList<Match> alMatchTmp) {
		Match match1 = getMatchViaInfo(match.getDate(), match.getEquipe1()
				.getNom(), alMatchTmp);
		Match match2 = getMatchViaInfo(match.getDate(), match.getEquipe2()
				.getNom(), alMatchTmp);

		/** @todo logique plus simple ?? */
		if (match1 == null || match2 == null)
			return false;

		return match1.getEquipe1().getNom().equals(match2.getEquipe1().getNom())
				&& match1.getEquipe2().getNom().equals(match2.getEquipe2().getNom())
				|| match1.getEquipe1().getNom().equals(match2.getEquipe2().getNom())
				&& match1.getEquipe2().getNom().equals(match2.getEquipe1().getNom());
	}

	public void chargerListeMatchsApronostiquer() {
		System.out.println("charger");
		File file = new File("listeMatchsApronostiquer.dat");
		if (file.exists()) {
			try {

				FileInputStream fichier = new FileInputStream(
						"listeMatchsApronostiquer.dat");
				ObjectInputStream ois = new ObjectInputStream(fichier);
				alMatchs = (ArrayList<Match>) ois.readObject();

			} catch (java.io.IOException e) {
				System.out.println("Erreur 01 chargement liste pronostiques");
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				System.out.println("Erreur 02 chargement liste pronostiques");
				e.printStackTrace();
			}
		} else
			alMatchs = new ArrayList<Match>();
	}

	public void sauvegarderListeMatchsApronostiquer() {
		System.out.println("sauvegarder");
		try {
			FileOutputStream fichier = new FileOutputStream(
					"listeMatchsApronostiquer.dat");
			ObjectOutputStream oos = new ObjectOutputStream(fichier);
			oos.writeObject(alMatchs);
			oos.flush();
			oos.close();
		} catch (java.io.IOException e) {
			System.out.println("Erreur sauvegarde listeMatchs " + e);
			e.printStackTrace();
		}
	}

	public void chargerListeUtilisateurs() {
		File file = new File("listeUtilisateurs.dat");
		if (file.exists()) {
			try {
				FileInputStream fichier = new FileInputStream(
						"listeUtilisateurs.dat");
				ObjectInputStream ois = new ObjectInputStream(fichier);
				alUtilisateurs = (ArrayList<Utilisateur>) ois.readObject();
				// for(Utilisateur user : alUtilisateurs) {
				// System.out.println(user.getPseudo() + " "+
				// user.getListePronostique().size());
				// }
			} catch (java.io.IOException e) {
				System.out.println("Erreur 01 chargement liste utilisateurs");
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				System.out.println("Erreur 02 chargement liste utilisateurs");
				e.printStackTrace();
			}
		} else
			alUtilisateurs = new ArrayList<Utilisateur>();
	}

	public void sauvegarderListeUtilisateurs() {
		try {
			FileOutputStream fichier = new FileOutputStream(
					"listeUtilisateurs.dat");
			ObjectOutputStream oos = new ObjectOutputStream(fichier);
			oos.writeObject(alUtilisateurs);
			oos.flush();
			oos.close();
		} catch (java.io.IOException e) {
			System.out.println("Erreur sauvegarde listeUtilisateur " + e);
			e.printStackTrace();
		}
	}

	public void chargerListeEquipes() {
		System.out.println("charger");
		File file = new File("listeEquipes.dat");
		if (file.exists()) {
			try {
				FileInputStream fichier = new FileInputStream(
						"listeEquipes.dat");
				ObjectInputStream ois = new ObjectInputStream(fichier);
				alEquipes = (ArrayList<Equipe>) ois.readObject();

			} catch (java.io.IOException e) {
				System.out.println("Erreur 01 chargement liste équipes");
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				System.out.println("Erreur 02 chargement liste équipes");
				e.printStackTrace();
			}
		} else
			alEquipes = new ArrayList<Equipe>();
	}

	public void sauvegarderListeEquipes() {
		System.out.println("sauvegarder");
		try {
			FileOutputStream fichier = new FileOutputStream("listeEquipes.dat");
			ObjectOutputStream oos = new ObjectOutputStream(fichier);
			oos.writeObject(alEquipes);
			oos.flush();
			oos.close();
		} catch (java.io.IOException e) {
			System.out.println("Erreur sauvegarde listeEquipe " + e);
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		Controleur ctrl = new Controleur();
		new FenetrePrincipale(ctrl);
	}
}
